@use 'sass:math';
@use '@angular/cdk';
@use './m3-stepper';
@use '../core/tokens/token-utils';
@use './stepper-variables';

// Gets the `calc` expression for the vertical padding of the stepper header.
@function _get-vertical-padding-calc() {
  $height: token-utils.slot(stepper-header-height, $fallbacks);
  @return calc(calc(#{$height} - #{stepper-variables.$label-header-height}) / 2);
}

$fallbacks: m3-stepper.get-tokens();

.mat-stepper-vertical,
.mat-stepper-horizontal {
  display: block;
  font-family: token-utils.slot(stepper-container-text-font, $fallbacks);
  background: token-utils.slot(stepper-container-color, $fallbacks);
}

.mat-horizontal-stepper-header-container {
  white-space: nowrap;
  display: flex;
  align-items: center;

  .mat-stepper-label-position-bottom & {
    align-items: flex-start;
  }

  .mat-stepper-header-position-bottom & {
    order: 1;
  }
}

.mat-stepper-horizontal-line {
  border-top-width: stepper-variables.$line-width;
  border-top-style: solid;
  flex: auto;
  height: 0;
  margin: 0 stepper-variables.$line-gap - stepper-variables.$side-gap;
  min-width: stepper-variables.$line-gap + stepper-variables.$side-gap;
  border-top-color: token-utils.slot(stepper-line-color, $fallbacks);

  .mat-stepper-label-position-bottom & {
    $vertical-padding: _get-vertical-padding-calc();
    margin: 0;
    min-width: 0;
    position: relative;

    // Ensures that the horizontal line for the step content is aligned centered vertically.
    top: calc(#{$vertical-padding} + #{math.div(stepper-variables.$label-header-height, 2)});
  }
}

%mat-header-horizontal-line-label-position-bottom {
  $half-side-gap: math.div(stepper-variables.$side-gap, 2);
  border-top-width: stepper-variables.$line-width;
  border-top-style: solid;
  content: '';
  display: inline-block;
  height: 0;
  position: absolute;
  width: calc(50% - #{$half-side-gap + stepper-variables.$line-gap});
}

.mat-horizontal-stepper-header {
  display: flex;
  overflow: hidden;
  align-items: center;
  padding: 0 stepper-variables.$side-gap;
  height: token-utils.slot(stepper-header-height, $fallbacks);

  .mat-step-icon {
    margin-right: stepper-variables.$line-gap;
    flex: none;

    [dir='rtl'] & {
      margin-right: 0;
      margin-left: stepper-variables.$line-gap;
    }
  }

  $vertical-padding: _get-vertical-padding-calc();

  &::before,
  &::after {
    border-top-color: token-utils.slot(stepper-line-color, $fallbacks);
  }

  .mat-stepper-label-position-bottom & {
    padding: #{$vertical-padding} stepper-variables.$side-gap;

    &::before,
    &::after {
      // Ensures that the horizontal lines for the step header are centered vertically.
      top: calc(#{$vertical-padding} + #{math.div(stepper-variables.$label-header-height, 2)});
    }
  }

  .mat-stepper-label-position-bottom & {
    box-sizing: border-box;
    flex-direction: column;
    // We use auto instead of fixed 104px (by spec) because when there is an optional step
    //  the height is greater than that
    height: auto;

    &:not(:last-child)::after,
    [dir='rtl'] &:not(:first-child)::after {
      @extend %mat-header-horizontal-line-label-position-bottom;
      right: 0;
    }

    &:not(:first-child)::before,
    [dir='rtl'] &:not(:last-child)::before {
      @extend %mat-header-horizontal-line-label-position-bottom;
      left: 0;
    }

    [dir='rtl'] &:last-child::before,
    [dir='rtl'] &:first-child::after {
      display: none;
    }

    & .mat-step-icon {
      // Cleans margin both for ltr and rtl direction
      margin-right: 0;
      margin-left: 0;
    }

    & .mat-step-label {
      padding: stepper-variables.$label-position-bottom-top-gap 0 0 0;
      text-align: center;
      width: 100%;
    }
  }
}

.mat-vertical-stepper-header {
  display: flex;
  align-items: center;

  // We can't use `max-height` here, because it breaks the flexbox centering in IE.
  height: stepper-variables.$label-header-height;

  padding: #{_get-vertical-padding-calc()} stepper-variables.$side-gap;

  .mat-step-icon {
    margin-right: stepper-variables.$vertical-stepper-content-margin - stepper-variables.$side-gap;

    [dir='rtl'] & {
      margin-right: 0;
      margin-left: stepper-variables.$vertical-stepper-content-margin - stepper-variables.$side-gap;
    }
  }
}

.mat-horizontal-stepper-wrapper {
  display: flex;
  flex-direction: column;
}

.mat-horizontal-stepper-content {
  visibility: hidden;
  overflow: hidden;
  outline: 0;
  height: 0;

  .mat-stepper-animations-enabled & {
    transition: transform var(--mat-stepper-animation-duration, 0) cubic-bezier(0.35, 0, 0.25, 1);
  }

  &.mat-horizontal-stepper-content-previous {
    transform: translate3d(-100%, 0, 0);
  }

  &.mat-horizontal-stepper-content-next {
    transform: translate3d(100%, 0, 0);
  }

  &.mat-horizontal-stepper-content-current {
    // TODO(crisbeto): the height and visibility switches are a bit jarring, but that's how the
    // animation was set up when we still used the Animations module. We should be able to make
    // it a bit smoother.
    visibility: visible;
    transform: none;
    height: auto;
  }

  .mat-stepper-horizontal:not(.mat-stepper-animating) &.mat-horizontal-stepper-content-current {
    overflow: visible;
  }
}

.mat-horizontal-content-container {
  overflow: hidden;
  padding: 0 stepper-variables.$side-gap stepper-variables.$side-gap stepper-variables.$side-gap;

  @include cdk.high-contrast {
    outline: solid 1px;
  }

  .mat-stepper-header-position-bottom & {
    padding: stepper-variables.$side-gap stepper-variables.$side-gap 0 stepper-variables.$side-gap;
  }
}

.mat-vertical-content-container {
  display: grid;
  grid-template-rows: 0fr;
  grid-template-columns: 100%;
  margin-left: stepper-variables.$vertical-stepper-content-margin;
  border: 0;
  position: relative;

  .mat-stepper-animations-enabled & {
    transition: grid-template-rows var(--mat-stepper-animation-duration, 0)
      cubic-bezier(0.4, 0, 0.2, 1);
  }

  &.mat-vertical-content-container-active {
    grid-template-rows: 1fr;
  }

  .mat-step:last-child & {
    border: none;
  }

  @include cdk.high-contrast {
    outline: solid 1px;
  }

  [dir='rtl'] & {
    margin-left: 0;
    margin-right: stepper-variables.$vertical-stepper-content-margin;
  }


  // All the browsers we support have support for `grid` as well, but given that these styles are
  // load-bearing for the stepper, we have a fallback to height which doesn't animate, just in case.
  // stylelint-disable material/no-prefixes
  @supports not (grid-template-rows: 0fr) {
    height: 0;

    &.mat-vertical-content-container-active {
      height: auto;
    }
  }
  // stylelint-enable material/no-prefixes
}

.mat-stepper-vertical-line::before {
  content: '';
  position: absolute;
  left: 0;
  border-left-width: stepper-variables.$line-width;
  border-left-style: solid;

  $vertical-padding: _get-vertical-padding-calc();
  $vertical-offset: calc(#{stepper-variables.$line-gap} - #{$vertical-padding});

  border-left-color: token-utils.slot(stepper-line-color, $fallbacks);

  // Ensures that the vertical lines for the step content exceed into the step
  // headers with a given distance (`$mat-stepper-line-gap`) to the step icon.
  top: $vertical-offset;
  bottom: $vertical-offset;

  [dir='rtl'] & {
    left: auto;
    right: 0;
  }
}

.mat-vertical-stepper-content {
  overflow: hidden;
  outline: 0;
  visibility: hidden;

  .mat-stepper-animations-enabled & {
    transition: visibility var(--mat-stepper-animation-duration, 0) linear;
  }

  .mat-vertical-content-container-active > & {
    visibility: visible;
  }
}

.mat-vertical-content {
  padding: 0 stepper-variables.$side-gap stepper-variables.$side-gap stepper-variables.$side-gap;
}
